package top.chukongxiang.project.base.utils;

import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Map对象工具类
 * 包: op.chukongxiang.dubboboot.simple.common.utils
 * 作者: chukongxiang
 * 时间: 2020/6/5 - 2:41 下午
 */
public class MapUtils {

    /**
     * 符合条件的将会被返回
     * @param map
     * @param compare(k,v)
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K,V> Map<K,V> filter(Map<K,V> map, BiPredicate<K, V> compare) {
        Set<Map.Entry<K, V>> entries = map.entrySet();
        List<Map.Entry<K, V>> list = new ArrayList<>(entries);
        list = ArrayUtils.filter(list, kvEntry -> compare.test(kvEntry.getKey(), kvEntry.getValue()));
        return ArrayUtils.toMap(list, Map.Entry::getKey, Map.Entry::getValue);
    }

    /**
     * 符合条件的将会被返回
     * @param map
     * @param entryCompare(entry)
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K,V> Map<K,V> filter(Map<K,V> map, Predicate<Map.Entry<K,V>> entryCompare) {
        Set<Map.Entry<K, V>> entries = map.entrySet();
        List<Map.Entry<K, V>> list = new ArrayList<>(entries);
        list = ArrayUtils.filter(list, entryCompare);
        return ArrayUtils.toMap(list, Map.Entry::getKey, Map.Entry::getValue);
    }

    /**
     * 符合条件的将会被删除
     * @param map
     * @param compare(k,v)
     * @param <K>
     * @param <V>
     */
    public static <K,V> void removeIf(Map<K,V> map, BiPredicate<K, V> compare) {
        List<K> removeIndies = new ArrayList<>();
        map.forEach((k, v) -> {
            if (compare.test(k, v)) {
                removeIndies.add(k);
            }
        });
        removeIndies.forEach(map::remove);
    }

    /**
     * 符合条件的将会被删除
     * @param map
     * @param entryCompare(entry)
     * @param <K>
     * @param <V>
     */
    public static <K,V> void removeIf(Map<K,V> map, Predicate<Map.Entry<K,V>> entryCompare) {
        List<Map.Entry<K,V>> removeIndies = new ArrayList<>();
        map.entrySet().forEach(entry -> {
            if (entryCompare.test(entry)) {
                removeIndies.add(entry);
            }
        });
        removeIndies.forEach(entry -> map.remove(entry.getKey()));
    }

    /**
     * map中的value转为list
     * @param map
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K,V> List<V> getValuesToList(Map<K,V> map) {
        List<V> rs = new ArrayList<>();
        map.forEach((k,v)-> rs.add(v));
        return rs;
    }

    /**
     * map类型转换（默认转为HashMap）
     * @param map 原map
     * @param toKey 将key转换为哪种类型
     * @param toValue 将value转换为哪种类型
     * @param <K>
     * @param <V>
     * @param <E>
     * @param <R>
     * @return
     */
    public static <K,V,E,R> Map<E,R> convert(Map<K,V> map, Function<K,E> toKey, Function<V, R> toValue) {
        return convert(map, new HashMap<>(), toKey, toValue);
    }

    /**
     * map类型转换
     * @param map 原map
     * @param instance 目标Map对象
     * @param toKey 将key转换为哪种类型
     * @param toValue 将value转换为哪种类型
     * @param <K>
     * @param <V>
     * @param <E>
     * @param <R>
     * @return
     */
    public static <K,V,E,R> Map<E,R> convert(Map<K,V> map, Map<E,R> instance, Function<K,E> toKey, Function<V, R> toValue) {
        map.forEach((k,v)-> instance.put(toKey.apply(k), toValue.apply(v)));
        return instance;
    }

}
